#include <iostream>
#include "Poco/UnicodeConverter.h"
#include "Poco/UTF8Encoding.h"
#include "Poco/Windows936Encoding.h"
#include "Poco/TextConverter.h"
#include "Poco/Exception.h"
#include "Encoding.h"

using namespace SystemTool;

// UTF8 -> GBK
std::string Encoding::UTF8ToGBK(std::string strUtf8)
{
    if(strUtf8.empty())
    {
        return "";
    }
    std::string strGBK = "";
    try
    {
        Poco::UTF8Encoding utf8Encoding;
        Poco::Windows936Encoding cp936Encoding;
        Poco::TextConverter converter(utf8Encoding, cp936Encoding);
        converter.convert(strUtf8, strGBK);
    }
    catch(Poco::Exception& e)
    {
        std::cout << "Failed to transfer UTF8->GBK with err:" << e.displayText() << std::endl;
    }

    return strGBK;
}

// UTF8 -> UTF16
std::wstring Encoding::UTF8ToUTF16(std::string strUtf8)
{
    if(strUtf8.empty())
    {
        return L"";
    }
    std::wstring strUtf16 = L"";
    try
    {
        Poco::UnicodeConverter::convert(strUtf8,strUtf16);
    }
    catch(Poco::Exception& e)
    {
        std::cout << "Failed to transfer UTF8->UTF16 with err:" << e.displayText() << std::endl;
    }

    return strUtf16;
}

// UTF8 -> UTF32
std::wstring Encoding::UTF8ToUTF32(std::string strUtf8)
{
    if(strUtf8.empty())
    {
        return L"";
    }
    std::wstring strUtf32 = L"";
    try
    {
        Poco::UnicodeConverter::convert(strUtf8,strUtf32);
    }
    catch(Poco::Exception& e)
    {
        std::cout << "Failed to transfer UTF8->UTF32 with err:" << e.displayText() << std::endl;
    }

    return strUtf32;
}

// GBK -> UTF8
std::string Encoding::GBKToUTF8(std::string strGBK)
{
    if(strGBK.empty())
    {
        return "";
    }
    std::string strUtf8Data = "";
    try
    {
        Poco::Windows936Encoding cp936Encoding;
        Poco::UTF8Encoding utf8Encoding;
        Poco::TextConverter converter(cp936Encoding, utf8Encoding);
        converter.convert(strGBK, strUtf8Data);
    }
    catch(Poco::Exception& e)
    {
        std::cout << "Failed to transfer GBK->UTF8 with err:" << e.displayText() << std::endl;
    }

    return strUtf8Data;
}

// UTF16 -> UTF8
std::string Encoding::UTF16ToUTF8(std::wstring strUtf16)
{
    if(strUtf16.empty())
    {
        return "";
    }
    std::string strUtf8Data = "";
    try
    {
        Poco::UnicodeConverter::convert(strUtf16,strUtf8Data);
    }
    catch(Poco::Exception& e)
    {
        std::cout << "Failed to transfer UTF16->UTF8 with err:" << e.displayText() << std::endl;
    }

    return strUtf8Data;
}

// UTF32 ->UTF8
std::string Encoding::UTF32ToUTF8(std::wstring strUtf32)
{
    if(strUtf32.empty())
    {
        return "";
    }
    std::string strUtf8Data = "";
    try
    {
        Poco::UnicodeConverter::convert(strUtf32,strUtf8Data);
    }
    catch(Poco::Exception& e)
    {
        std::cout << "Failed to transfer UTF32->UTF8 with err:" << e.displayText() << std::endl;
    }

    return strUtf8Data;
}

// UTF16 -> GBK
std::string Encoding::UTF16ToGBK(std::wstring strUtf16)
{
    // UTF16->UTF8
    std::string strUtf8 = UTF16ToUTF8(strUtf16);
    
    // UTF8->GBK
    return UTF8ToGBK(strUtf8);
}

// GBK -> UTF16
std::wstring Encoding::GBKToUTF16(std::string strGBK)
{
    // GBK -> UTF8
    std::string strUtf8 = GBKToUTF8(strGBK);

    // UTF8 -> UTF16
    return UTF8ToUTF16(strUtf8);
}

// UTF32 -> GBK
std::string Encoding::UTF32ToGBK(std::wstring strUtf32)
{
    // UTF32 ->UTF8
    std::string strUtf8 = UTF32ToUTF8(strUtf32);

    // UTF8 -> GBK
    return UTF8ToGBK(strUtf8);
}

// GBK -> UTF32
std::wstring Encoding::GBKToUTF32(std::string strGBK)
{
    // GBK -> UTF8
    std::string strUtf8 = GBKToUTF8(strGBK);

    // UTF8 -> UTF32
    return UTF8ToUTF32(strUtf8);
}

// UTF16 -> UTF32
std::wstring Encoding::UTF16ToUTF32(std::wstring strUtf16)
{
    // UTF16->UTF8
    std::string strUtf8 = UTF16ToUTF8(strUtf16);

    return UTF8ToUTF32(strUtf8);
}

// UTF32 -> UTF16
std::wstring Encoding::UTF32ToUTF16(std::wstring strUtf32)
{
    // UTF32 ->UTF8
    std::string strUtf8 = UTF32ToUTF8(strUtf32);

    return UTF8ToUTF16(strUtf8);
}
